home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "global.h"
- #include "mbuf.h"
- #include "timer.h"
- #include "proc.h"
- #include "iface.h"
- #include "ax25.h"
- #include "lapb.h"
- #include "cmdparse.h"
- #include "socket.h"
- #include "ax25tnc.h"
- #include "ax_mbx.h"
- #include "session.h"
- #include "tty.h"
- #include "nr4.h"
- #include "commands.h"
-
- extern char Notval[];
-
- static void ax_in __ARGS((int unused,void *tnc1,void *p));
- static int doaxirtt __ARGS((int argc,char *argv[],void *p));
- static int doaxkick __ARGS((int argc,char *argv[],void *p));
- static int doaxreset __ARGS((int argc,char *argv[],void *p));
- static int doaxroute __ARGS((int argc,char *argv[],void *p));
- static int doaxstat __ARGS((int argc,char *argv[],void *p));
- static int doaxwindow __ARGS((int argc,char *argv[],void *p));
- static int dodigipeat __ARGS((int argc,char *argv[],void *p));
- static int domaxframe __ARGS((int argc,char *argv[],void *p));
- static int domycall __ARGS((int argc,char *argv[],void *p));
- static int don2 __ARGS((int argc,char *argv[],void *p));
- static int dopaclen __ARGS((int argc,char *argv[],void *p));
- static int dopthresh __ARGS((int argc,char *argv[],void *p));
- static int dot3 __ARGS((int argc,char *argv[],void *p));
- static int doversion __ARGS((int argc,char *argv[],void *p));
-
- char *Ax25states[] = {
- "Disconnected",
- "Listening",
- "Conn pending",
- "Disc pending",
- "Connected",
- "Recovery",
- "Frame Reject",
- };
-
- /* Ascii explanations for the disconnect reasons listed in lapb.h under
- * "reason" in ax25_cb
- */
- char *Axreasons[] = {
- "Normal",
- "DM received",
- "Timeout"
- };
-
- static struct cmds Axcmds[] = {
- "digipeat", dodigipeat, 0, 0, NULLCHAR,
- "irtt", doaxirtt, 0, 0, NULLCHAR,
- "kick", doaxkick, 0, 2, "ax25 kick <axcb>",
- "maxframe", domaxframe, 0, 0, NULLCHAR,
- "mycall", domycall, 0, 0, NULLCHAR,
- "paclen", dopaclen, 0, 0, NULLCHAR,
- "pthresh", dopthresh, 0, 0, NULLCHAR,
- "reset", doaxreset, 0, 2, "ax25 reset <axcb>",
- "retry", don2, 0, 0, NULLCHAR,
- "route", doaxroute, 0, 0, NULLCHAR,
- "status", doaxstat, 0, 0, NULLCHAR,
- "t3", dot3, 0, 0, NULLCHAR,
- "version", doversion, 0, 0, NULLCHAR,
- "window", doaxwindow, 0, 0, NULLCHAR,
- NULLCHAR,
- };
- /* Multiplexer for top-level ax25 command */
- int
- doax25(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return subcmd(Axcmds,argc,argv,p);
- }
-
- static
- doaxreset(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct ax25_cb *axp;
-
- axp = (struct ax25_cb *)ltop(htol(argv[1]));
- if(!ax25val(axp)){
- printf(Notval);
- return 1;
- }
- reset_ax25(axp);
- return 0;
- }
-
- /* Display AX.25 link level control blocks */
- static
- doaxstat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register int i;
- register struct ax25_cb *axp;
- char tmp[10];
-
- if(argc < 2){
- printf(" &AXB Snd-Q Rcv-Q Remote State\n");
- for(i=0;i<NHASH;i++){
- for(axp = Ax25_cb[i];axp != NULLAX25; axp = axp->next){
- pax25(tmp,&axp->remote);
- printf("%8lx %-8d%-8d%-10s%s\n",
- ptol(axp),
- len_q(axp->txq),len_mbuf(axp->rxq),
- tmp,Ax25states[axp->state]);
- }
- }
- return 0;
- }
- axp = (struct ax25_cb *)ltop(htol(argv[1]));
- if(!ax25val(axp)){
- printf(Notval);
- return 1;
- }
- st_ax25(axp);
- return 0;
- }
- /* Dump one control block */
- void
- st_ax25(axp)
- register struct ax25_cb *axp;
- {
- char tmp[10];
-
- if(axp == NULLAX25)
- return;
- printf(" &AXB Remote RB V(S) V(R) Unack P Retry State\n");
- pax25(tmp,&axp->remote);
- printf("%8lx %-9s",ptol(axp),tmp);
- putchar(axp->flags.rejsent ? 'R' : ' ');
- putchar(axp->flags.remotebusy ? 'B' : ' ');
- printf(" %4d %4d",axp->vs,axp->vr);
- printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
- printf(" %02u/%02u",axp->retries,axp->n2);
- printf(" %s\n",Ax25states[axp->state]);
-
- printf("SRT = %lu ",axp->srt * MSPTICK);
- printf("T1: ");
- if(run_timer(&axp->t1))
- printf("%lu",read_timer(&axp->t1) * MSPTICK);
- else
- printf("stop");
- printf("/%lu ms; ",dur_timer(&axp->t1) * MSPTICK);
-
- printf("T3: ");
- if(run_timer(&axp->t3))
- printf("%lu",read_timer(&axp->t3) * MSPTICK);
- else
- printf("stop");
- printf("/%lu ms\n",dur_timer(&axp->t3) * MSPTICK);
-
- }
-
- /* Display or change our AX.25 address */
- static
- domycall(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char buf[15];
-
- if(argc < 2){
- pax25(buf,&Mycall);
- printf("%s\n",buf);
- return 0;
- }
- if(setcall(&Mycall,argv[1]) == -1)
- return -1;
- Mycall.ssid |= E;
- return 0;
- }
-
- /* Control AX.25 digipeating */
- static
- dodigipeat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Digipeat,"Digipeat",argc,argv);
- }
- static
- doversion(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&Axversion,"AX25 version",argc,argv);
- }
-
- static
- doaxirtt(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
- }
-
- /* Set idle timer */
- static
- dot3(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
- }
-
- /* Set retry limit count */
- static
- don2(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&N2,"Retry limit",argc,argv);
- }
- /* Force a retransmission */
- static
- doaxkick(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct ax25_cb *axp;
-
- axp = (struct ax25_cb *)ltop(htol(argv[1]));
- if(!ax25val(axp)){
- printf(Notval);
- return 1;
- }
- kick_ax25(axp);
- return 0;
- }
- /* Set maximum number of frames that will be allowed in flight */
- static
- domaxframe(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&Maxframe,"Window size (frames)",argc,argv);
- }
-
- /* Set maximum length of I-frame data field */
- static
- dopaclen(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
- }
- /* Set size of I-frame above which polls will be sent after a timeout */
- static
- dopthresh(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
- }
-
- /* Set high water mark on receive queue that triggers RNR */
- static
- doaxwindow(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
- }
- /* End of ax25 subcommands */
-
- /* Initiate interactive AX.25 connect to remote station */
- int
- doconnect(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct sockaddr_ax fsocket;
- struct session *sp;
-
- /* Allocate a session descriptor */
- if((sp = newsession(argv[2],AX25TNC)) == NULLSESSION){
- printf("Too many sessions\n");
- freeargs(argc,argv);
- return 1;
- }
- if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
- freesession(sp);
- printf("Can't create socket\n");
- freeargs(argc,argv);
- return 1;
- }
- fsocket.sax_family = AF_AX25;
- setcall(&fsocket.ax25_addr,argv[2]);
- strncpy(fsocket.iface,argv[1],ILEN);
- freeargs(argc,argv);
- printf("Trying %s...\n",psocket((struct sockaddr *)&fsocket));
- return axnrconnect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
- }
-
- /* Generic interactive connect routine, used by both AX.25 and NET/ROM */
- int
- axnrconnect(sp, fsocket, len)
- struct session *sp;
- char *fsocket;
- int len;
- {
- struct mbuf *bp;
- char *cp;
-
- Current = sp;
- Mode = CONV_MODE;
- sp->cb.ax25 = (struct ax25tnc *)calloc(1,sizeof(struct ax25tnc));
- sp->cb.ax25->session = sp;
- sp->cb.ax25->output = Curproc;
- if(connect(sp->s,fsocket,len) == -1){
- printf("%s session %u failed: %s errno %d\n",
- Sestypes[sp->type],(unsigned)(sp-Sessions),
- sockerr(sp->s),errno);
- close_s(sp->s);
- free((char *)sp->cb.ax25);
- freesession(sp);
- return 1;
- }
- printf("%s session %u connected to %s\n",Sestypes[sp->type],
- (unsigned)(sp-Sessions),sp->name);
- sp->cb.ax25->output = Curproc;
- sp->cb.ax25->input = newproc("ax_in",1024,ax_in,0,sp->cb.ax25,NULL);
- for(;;){
- while(sp->input == NULLBUF)
- pwait(&sp->input);
-
- bp = dequeue(&sp->input);
-
- /* If we're recording, record it */
- if(sp->record != NULLFILE)
- write_p(sp->record,bp);
-
- /* Get rid of the trailing newline */
- if((cp = strchr(bp->data,'\n')) != NULLCHAR){
- *cp = '\0';
- bp->cnt--;
- }
- if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
- break;
- }
- killproc(sp->cb.ax25->input);
- close_s(sp->s);
- free(sp->cb.ax25);
- freesession(sp);
- return 0;
- }
- /* Display and modify AX.25 routing table */
- static int
- doaxroute(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char buf[30];
- int i,j,ndigis;
- register struct ax_route *axr;
- struct ax25_addr target,digis[MAXDIGIS];
-
- if(argc < 2){
- printf("Target Type Digipeaters\n");
- for(i=0;i<NAXROUTE;i++){
- for(axr = Ax_routes[i];axr != NULLAXR;axr = axr->next){
- pax25(buf,&axr->target);
- printf("%-10s%-6s",buf,
- axr->type == AX_LOCAL ? "Local":"Auto");
- for(j=0;j<axr->ndigis;j++){
- pax25(buf,&axr->digis[j]);
- printf(" %s",buf);
- }
- printf("\n");
- }
- }
- return 0;
- }
- if(argc < 3){
- printf("Usage: ax25 route add <target> [digis...]\n");
- printf(" ax25 route drop <target>\n");
- return 1;
- }
- if(setcall(&target,argv[2]) == -1){
- printf("Bad target %s\n",argv[2]);
- return 1;
- }
- switch(argv[1][0]){
- case 'a': /* Add route */
- if(argc < 3){
- printf("Usage: ax25 route add <target> [digis...]\n");
- return 1;
- }
- ndigis = argc - 3;
- for(i=0;i<ndigis;i++){
- if(setcall(&digis[i],argv[i+3]) == -1){
- printf("Bad digipeater %s\n",argv[i+3]);
- return 1;
- }
- }
- if(ax_add(&target,AX_LOCAL,&digis[0],ndigis) == NULLAXR){
- printf("Failed\n");
- return 1;
- }
- break;
- case 'd': /* Drop route */
- if(ax_drop(&target) == -1){
- printf("Not in table\n");
- return 1;
- }
- break;
- default:
- printf("Unknown command %s\n",argv[1]);
- return 1;
- }
- return 0;
- }
- /* Upload process for both AX.25 and NET/ROM sessions */
- void
- ax_upload(unused,sp1,p)
- int unused;
- void *sp1;
- void *p;
- {
- struct mbuf *bp;
- char *cp;
- int c,bufsize;
- struct session *sp;
-
- sp = (struct session *)sp1;
- /* NET/ROM is a sequenced packet protocol, so we have to make sure
- that the length of each packet is within legal limits */
- if (sp->type == NRSESSION)
- bufsize = NR4MAXINFO;
- else
- bufsize = BUFSIZ;
- for(;;){
- bp = alloc_mbuf(bufsize);
- cp = bp->data;
- while(bp->cnt < bufsize){
- if((c = getc(sp->upload)) == EOF)
- break;
- if(c == '\r')
- continue;
- if(c == '\n')
- c = '\r';
- *cp++ = c;
- bp->cnt++;
- }
- if(bp->cnt == 0){
- free_p(bp);
- break;
- } else if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
- break;
- }
- fclose(sp->upload);
- sp->upload = NULLFILE;
- free(sp->ufile);
- sp->ufile = NULLCHAR;
- sp->cb.ax25->upload = NULLPROC;
- }
- /* AX.25 TNC receive process, used by both AX.25 and NET/ROM sessions */
- static void
- ax_in(unused,tnc1,p)
- int unused;
- void *tnc1;
- void *p;
- {
- char c;
- struct session *sp;
- char *cp;
- struct mbuf *bp;
- int s;
- struct ax25tnc *tnc;
-
- tnc = (struct ax25tnc *)tnc1;
- sp = tnc->session;
- s = sp->s;
-
- for(;;){
- if(recv_mbuf(s,&bp,0,0,NULLCHAR,0) == -1)
- break;
- while(pullup(&bp,&c,1) == 1){
- /* Suspend output if we're not current */
- while(Current != sp || Mode != CONV_MODE)
- pwait(sp);
-
- putchar(c);
- if(c == '\r')
- putchar('\n');
-
- if(sp->record != NULLFILE){
- #ifdef UNIX
- if(c != '\r')
- #endif
- putc(c,sp->record);
- if(c == '\r')
- putc('\n',sp->record);
- }
- }
- }
- /* Close seen from remote host */
- cp = sockerr(s);
- printf("%s session %u closed: %s\n", Sestypes[sp->type],
- (unsigned)(sp - Sessions),
- cp != NULLCHAR ? cp : "EOF");
- close_s(s);
- tnc->input = NULLPROC;
- killproc(tnc->output);
- free((char *)tnc);
- freesession(sp);
- }
-
- int
- ax25start(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int s;
- char buf[80];
-
- freeargs(argc,argv); /* Args are not used */
- if (Axi_sock != -1)
- return 0;
-
- psignal(Curproc,0); /* Don't keep the parser waiting */
- chname(Curproc,"AX25 listener");
- Axi_sock = socket(AF_AX25,SOCK_STREAM,0);
- /* bind() is done automatically */
- if(listen(Axi_sock,1) == -1){
- close_s(Axi_sock);
- return -1;
- }
- for(;;){
- if((s = accept(Axi_sock,NULLCHAR,NULLINT)) == -1)
- break; /* Service is shutting down */
-
- if(Ax25mbox){
- /* Eat the line that triggered the connection
- * and then start the mailbox
- */
- recvline(s,buf,80);
- newproc("mbox",2048,mbx_incom,s,(void *)AX25TNC,NULL);
- } else
- newproc("in_ax25",2048,axnrhandle,s,(void *)AX25TNC,NULL);
- }
- close_s(Axi_sock);
- Axi_sock = -1;
- return 0;
- }
- int
- ax250(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- close_s(Axi_sock);
- Axi_sock = -1;
- return 0;
- }
- /* This function handles both incoming AX25 and NETROM sessions */
- void
- axnrhandle(s,t,p)
- int s;
- void *t;
- void *p;
- {
- int type;
- struct session *sp;
- char buf[20], *cp;
- struct mbuf *bp;
- char addr[MAXSOCKSIZE];
- int len = MAXSOCKSIZE;
-
- type = (int)t;
- sockowner(s,Curproc); /* We own it now */
- sprintf(buf,"open %s",Sestypes[type]);
- log(s,buf);
- /* Allocate a session descriptor */
- if((sp = newsession(NULLCHAR,type)) == NULLSESSION){
- usprintf(s,"Too many sessions\n");
- close_s(s);
- }
- getpeername(s,addr,&len);
- printf("\007Incoming %s session %u from %s\007\n",Sestypes[type],
- (unsigned)(sp - Sessions),psocket(addr));
- sp->cb.ax25 = (struct ax25tnc *)calloc(1,sizeof(struct ax25tnc));
- sp->cb.ax25->session = sp;
- sp->cb.ax25->output = Curproc;
- sp->s = s;
- sp->ttymode = TTY_EDIT|TTY_ECHO;
- sp->cb.ax25->input = newproc("ax_in",1024,ax_in,0,sp->cb.ax25,NULL);
- for(;;){
- while(sp->input == NULLBUF)
- pwait(&sp->input);
-
- bp = dequeue(&sp->input);
-
- /* If we're recording, record it */
- if(sp->record != NULLFILE)
- write_p(sp->record,bp);
-
- /* Get rid of the trailing newline */
- if((cp = strchr(bp->data,'\n')) != NULLCHAR){
- *cp = '\0';
- bp->cnt--;
- }
- if(send_mbuf(s,bp,0,NULLCHAR,0) == -1)
- break;
- }
- killproc(sp->cb.ax25->input);
- close_s(s);
- free((char *)sp->cb.ax25);
- freesession(sp);
- }
-